//======================================================================
//    This file is part of baijie_interface
//
//    Copyright (C) 2023 Shenzhen Baijie Technology Co., Ltd.All rights reserved.
//
//    filename : bluetooth_thread.cpp
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//======================================================================

#include "bluetooth_thread.h"

static QBluetoothDeviceDiscoveryAgent *g_discoveryAgent;
static QList<QBluetoothDeviceInfo> g_devices;  // Store the scanned device information
static QTimer *g_scanTimeoutTimer;
static QTimer *g_pairTimeoutTimer;
static QTimer *g_connectTimeoutTimer;
static QBluetoothLocalDevice *g_localDevice;
static QBluetoothAddress g_connectAddress;
static QBluetoothAddress g_pairAddress;
static int g_bluetoothConnectFlag=0;

bluetooth_thread::bluetooth_thread(QObject *parent) : QObject(parent)
{
    g_localDevice = new QBluetoothLocalDevice(this);
    g_discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
    g_scanTimeoutTimer = new QTimer(this);
    g_pairTimeoutTimer = new QTimer(this);
    g_connectTimeoutTimer = new QTimer(this);

    connect(g_discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,
            this, &bluetooth_thread::device_discovered);
    connect(g_discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished,
            this, &bluetooth_thread::scan_finished);
    connect(g_scanTimeoutTimer, &QTimer::timeout, this, &bluetooth_thread::bluetooth_scan_timer);
    connect(g_pairTimeoutTimer, &QTimer::timeout, this, &bluetooth_thread::bluetooth_pair_timer);
    connect(g_connectTimeoutTimer, &QTimer::timeout, this, &bluetooth_thread::bluetooth_connect_timer);
    connect(g_localDevice, &QBluetoothLocalDevice::pairingFinished,
            this, &bluetooth_thread::pair_finished);
}

void bluetooth_thread::bluetooth_init_thread()
{
    g_bluetoothInterface->bluetoothInint();
}

void bluetooth_thread::bluetooth_scan_thread()
{
    if(g_scanTimeoutTimer->isActive())
        return;

    g_discoveryAgent->start();
    g_scanTimeoutTimer->start(3000);
}

void bluetooth_thread::bluetooth_scan_stop_thread()
{
    g_discoveryAgent->stop();
    g_scanTimeoutTimer->stop();
}

void bluetooth_thread::bluetooth_pair_thread(QString btAddress)
{
    g_pairTimeoutTimer->start(9000);
    QBluetoothAddress address(btAddress);
    g_pairAddress = address;
    g_localDevice->requestPairing(address, QBluetoothLocalDevice::Paired);
}

void bluetooth_thread::bluetooth_connect_thread(QString btAddress)
{
    g_connectAddress = QBluetoothAddress(btAddress);
    QBluetoothSocket *g_socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
    g_socket->connectToService(g_connectAddress, QBluetoothUuid(QBluetoothUuid::AudioSource));
    g_connectTimeoutTimer->start(4000);
}

void bluetooth_thread::device_discovered(const QBluetoothDeviceInfo &device)
{
    // Each time a device is discovered, the device information is stored
    if (device.name().isEmpty() || device.name() == device.address().toString())
        return;
    QString addressStr = device.address().toString().replace(":", "-");
    if (device.name() == addressStr)
        return;
    g_devices.append(device);
}

void bluetooth_thread::scan_finished()
{
    qDebug() << "Bluetooth scan finished. Devices found:";
    for (const QBluetoothDeviceInfo &device : g_devices)
    {
        qDebug() << "Device name:" << device.name() << ", Address:" << device.address().toString();
    }
}

void bluetooth_thread::bluetooth_scan_timer()
{
    QString str;
    g_discoveryAgent->stop(); // Stop scanning
    g_scanTimeoutTimer->stop();
    for (const QBluetoothDeviceInfo &device : g_devices)
    {
        str = str + "\t" + device.address().toString() + "\t" + device.name() + "\n";
    }
    str.chop(1);
    g_devices.clear();
    emit send_bluetooth_msg(EnumBtScanSignal,str);
}

void bluetooth_thread::bluetooth_pair_timer()
{
    g_pairTimeoutTimer->stop();
    g_localDevice->requestPairing(g_pairAddress, QBluetoothLocalDevice::Unpaired);
}

void bluetooth_thread::pair_finished(const QBluetoothAddress &device, QBluetoothLocalDevice::Pairing pairing)
{
    if(g_bluetoothConnectFlag == 1)
    {
        g_bluetoothConnectFlag = 0;
        return;
    }
    g_pairTimeoutTimer->stop();
    QString pairResult;
    if (pairing == QBluetoothLocalDevice::Paired)
    {
        pairResult = "successful";
    }
    else
    {
        pairResult = "failed";
    }
    emit send_bluetooth_msg(EnumBtPairSignal,pairResult);
}

void bluetooth_thread::bluetooth_connect_timer()
{
    QString connectResult;
    g_connectTimeoutTimer->stop();
    QList<QBluetoothAddress> connectedDevices = g_localDevice->connectedDevices();
    if (connectedDevices.isEmpty())
    {
        connectResult = "failed";
    }
    else
    {
        for (const QBluetoothAddress &address : connectedDevices)
        {
            if(g_connectAddress.toString() == address.toString())
            {
                connectResult = "successful";
                break;
            }
            else
                connectResult = "failed";
        }
    }
    emit send_bluetooth_msg(EnumBtConnectSignal,connectResult);
}

void bluetooth_thread::bluetoothRemove(QString btAddress)
{
    g_bluetoothConnectFlag = 1;
    QBluetoothAddress address(btAddress);
    g_localDevice->requestPairing(address, QBluetoothLocalDevice::Unpaired);
}

QString bluetooth_thread::getBluetoothName()
{
    g_localDevice;
    QString deviceName = g_localDevice->name();
    return deviceName;
}

void bluetooth_thread::bluetoothEnableFlag(bool flag)
{
    if(false == flag)
    {
        g_localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
    }
    else
    {
        g_localDevice->powerOn();
    }
}
